// 题目描述：
// 给定一个整数数组 nums，将数组中的元素向右轮转 k 个位置，其中 k 是非负数。

// 示例 1:

// 输入: nums = [1,2,3,4,5,6,7], k = 3
// 输出: [5,6,7,1,2,3,4]
// 解释:
// 向右轮转 1 步: [7,1,2,3,4,5,6]
// 向右轮转 2 步: [6,7,1,2,3,4,5]
// 向右轮转 3 步: [5,6,7,1,2,3,4]
// 示例 2:

// 输入：nums = [-1,-100,3,99], k = 2
// 输出：[3,99,-1,-100]
// 解释: 
// 向右轮转 1 步: [99,-1,-100,3]
// 向右轮转 2 步: [3,99,-1,-100]

// 要求：

// 尽可能想出更多的解决方案，至少有 三种 不同的方法可以解决这个问题。
// 你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗？

// 自己的答案（时间复杂度太高以及 LeetCode 限制数组不能 push 除 int 之外的其他类型导致不通过）：
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    if(nums.length < k) {
        k = k % nums.length
    }
    let cutNums = nums.splice(nums.length - k)
    cutNums.reverse().forEach(e => {
      nums.splice(0, 0, e)
    })

    // nums.unshift(cutNums)
    // nums.flat()

    // for(let i = k; i < nums.length; i++) {
    //     nums.splice(i, 1, nums[i])
    //     nums.unshift(nums[i])
    // }
};

// 官方题解：
// 方法一：使用辅助数组
// 这种方法比较直观，利用一个辅助数组来存储轮转后的结果。
var rotate = function(nums, k) {
    const n = nums.length;
    const newArr = new Array(n);
    for (let i = 0; i < n; ++i) {
        newArr[(i + k) % n] = nums[i];
    }
    for (let i = 0; i < n; ++i) {
        nums[i] = newArr[i];
    }
};

// 方法二：反转数组
// 这种方法通过三次反转来实现轮转：先反转整个数组，再分别反转前 k 个元素和后 n-k 个元素。
var rotate = function(nums, k) {
    function reverse(i, j) {
        while (i < j) {
            [nums[i], nums[j]] = [nums[j], nums[i]];
            i++;
            j--;
        }
    }

    const n = nums.length;
    k %= n; // 轮转 k 次等于轮转 k%n 次
    reverse(0, n - 1);
    reverse(0, k - 1);
    reverse(k, n - 1);
};

// 方法三：环状替换（原地算法）
// 这种方法通过模拟环状替换来原地实现轮转，空间复杂度为 O(1)。
function rotateArrayInPlace(nums, k) {  
    const n = nums.length;  
    k = k % n;  // 处理 k 大于数组长度的情况  
    let count = 0;  // 记录已经处理的元素个数  
  
    for (let start = 0; count < n; start++) {  
        let current = start;  
        let temp = nums[start];  
        let prev = nums[start];  
  
        do {  
            const next = (current + k) % n;  
            [nums[current], temp] = [temp, nums[next]];  
            prev = nums[current];  
            current = next;  
            count++;  
        } while (start !== current && prev === nums[start]);  // 防止进入已经处理过的环  
    }  
}  